package com.yao.mymvc.handlermapping;

import com.yao.myioc.aware.BeanFactoryAware;
import com.yao.myioc.definition.BeanDefinition;
import com.yao.myioc.factory.BeanFactory;
import com.yao.myioc.factory.support.DefaultListableBeanFactory;
import com.yao.mymvc.annotation.Controller;
import com.yao.mymvc.annotation.RequestMapping;
import com.yao.mymvc.handlermapping.iface.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 通过@RequestMapping注解将url与对应handler进行映射
 *
 * @author Henry Yao
 * @date 2021/5/2
 */
public class RequestMappingHandlerMapping implements HandlerMapping, BeanFactoryAware {
    /**
     * 用于存放url和对应处理方法
     */
    private Map<String, Object> handlerMappings = new HashMap<>();
    private DefaultListableBeanFactory beanFactory;

    /**
     * 获取对应url的处理方法
     *
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public Object getHandler(HttpServletRequest request) throws Exception {
        String requestURI = request.getRequestURI();
        return handlerMappings.get(requestURI);
    }

    /**
     * 初始化方法
     * 1、初始化url和方法的映射关系
     */
    public void init() {
        // 1、获取所有的bean的定义信息
        List<BeanDefinition> beanDefinitions = beanFactory.getBeanDefinitions();
        for (BeanDefinition bd : beanDefinitions) {
            try {
                Class<?> type = Class.forName(bd.getClazzName());
                // 2、判断是否被@Controller或者@RequestMapping修饰
                if (isHandler(type)){
                    // 2-1 获取被@RequestMapping修饰的方法
                    Method[] methods = type.getDeclaredMethods();
                    for (Method m:methods){
                        if (m.isAnnotationPresent(RequestMapping.class)) {
                            // 获取url
                            String value = m.getAnnotation(RequestMapping.class).value();
                            // 获取对应controller对象
                            Object bean = beanFactory.getBean(bd.getBeanName());
                            // 创建HandlerMethod对象
                            HandlerMethod handlerMethod = new HandlerMethod(bean, m);
                            // 放入集合
                            handlerMappings.put(value,handlerMethod);
                        }
                    }
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }

        }
        // 3、如果被@Controller或者@RequestMapping修饰则取出url与对应对象一起放到集合


    }

    private boolean isHandler(Class<?> type) {
        return type.isAnnotationPresent(Controller.class) || type.isAnnotationPresent(RequestMapping.class);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = (DefaultListableBeanFactory) beanFactory;
    }
}
